#![allow(dead_code)]

use clap::Parser;
use tokio::sync::watch;
use tracing::info;

use bc_manager::BcManagerHandler;
use mini_block_chain::Args;

pub mod local;

pub struct TestEnv {
    pub bc_manager: BcManagerHandler,
    pub shutdown_tx: watch::Sender<bool>,
    pub shutdown_rx: watch::Receiver<bool>,
    pub task_mine: Option<std::thread::JoinHandle<()>>,
}

pub async fn setup(
    db_path_prefix: &str,
    if_mining: bool,
    args: Option<Args>,
    enable_log: bool,
) -> (TestEnv, tempfile::TempDir) {
    let tmp_dir = bc_util::convert_to_temp_dir(db_path_prefix);
    let db_root_dir = tmp_dir.path().to_path_buf();

    let args = match args {
        Some(t) => t,
        None => {
            // Args::parse_from(["", "-p", "8080"])
            Args::parse_from([""])
        }
    };

    let (bc_manager, shutdown_tx, shutdown_rx, task_mine) =
        local::prepare_test_env(db_root_dir, &args, if_mining, enable_log).await;

    (
        TestEnv {
            bc_manager,
            shutdown_tx,
            shutdown_rx,
            task_mine,
        },
        tmp_dir,
    )
}

pub async fn shutdown_task_mine(env: &mut TestEnv) {
    info!("Shutting down task_mine...");
    let _ = env.shutdown_tx.send(true);

    if let Some(t) = env.task_mine.take() {
        t.join().unwrap();
    }
}

pub async fn teardown(mut env: TestEnv) {
    info!("Test done. Shutting down...");
    shutdown_task_mine(&mut env).await;
    mini_block_chain::cleanup_before_exit(env.bc_manager).await;
}

pub fn gen_default_args() -> Args {
    Args::parse_from([""])
}

pub async fn wait_for_shutdown_signal(
    shutdown_tx: watch::Sender<bool>,
    mut shutdown_rx: watch::Receiver<bool>,
    deadline_secs: u64,
) {
    let deadline = bc_util::create_delay_task(deadline_secs, shutdown_rx.clone());
    tokio::select! {
        _ = shutdown_rx.changed() => {
            if *shutdown_rx.borrow() {
                info!("Shutdown signal received for the event for APP loop task.");
            }
        }

        _ = tokio::signal::ctrl_c() => {
            println!("Received Ctrl+C signal, stopping P2P network of blockchain ...");
            let _ = shutdown_tx.send(true);
        }

        _ = deadline => {
            println!("Exiting after {}s", deadline_secs);
            let _ = shutdown_tx.send(true);
        }
    }
}
